<?php
declare (strict_types=1);

namespace app\topic\logic;

use app\common\exception\LogicException;
use app\common\logic\advert\AdvertLink;
use app\common\logic\category\Category;
use app\common\logic\Common;
use app\topic\event\subscribes\topic\Topic as TopicEvent;
use app\topic\model\Topic as TopicModel;
use app\topic\model\TopicComment;
use app\topic\model\TopicCommentLike as TCL;
use app\topic\model\TopicCommentReply as TCR;
use app\topic\model\TopicCommentReplyLike as TCRL;
use ArrayObject;
use think\db\exception\DbException;
use think\facade\Event;
use think\facade\Request;
use think\facade\View;
use think\Paginator;

/**
 * 资讯逻辑层
 */
class Topic extends TopicModel
{
    /**
     * 资讯首页 - PC
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-19
     */
    public function index($map, $mhm_id): array
    {
        // $field = 'id,title,abstract,cover,publish_time,read_count';
        // $list  = $this
        //         ->with(['cover_url'])
        //         ->field($field)
        //         ->where($map)
        //         ->order('update_time', 'DESC')
        //         ->paginate($this->getListRows());

        $banner   = app(AdvertLink::class)->getLinkUrlByKey('pc.topic.index');
        $splendid = $this->splendid('id,cover,title', 2, $mhm_id);
        $popular  = $this->popular('id,cover,title,publish_time,read_count', 5, $mhm_id);

        return [
            'banner'   => $banner,
            'splendid' => $splendid,
            // 'list'      => $list,
            'popular'  => $popular,
        ];
    }

    /**
     * 资讯列表
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-19
     *
     * @throws DbException
     */
    public function list($map): Paginator
    {
        $field = 'id,title,abstract,cover,publish_time,read_count,best_sort,update_time';
        return $this->with(['cover_url'])->field($field)->where($map)->order(['best_sort' => 'asc', 'update_time' => 'DESC'])
            // ->order('update_time', 'DESC')
            ->paginate(static::getListRows());
    }

    /**
     * 资讯详情
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-19
     *
     * @throws DbException
     */
    public function fetch($id): array
    {
        // 添加read_count
        $this->addReadCount($id);
        // 渲染
        $data = $this->with(['cover_url'])->findOrFail($id);
        // app
        $app = in_array(request()->device_type, ['android', 'ios']);
        // host
        $host   = request()->mhm_sdn ? request()->mhm_host : request()->pc_host;
        $domain = Request::domain();
        // 内容链接和文本格式
        $data->content_url  = $app ? $host . '/pageFound/topic/details?id=' . $id : $domain . '/topic/' . $id . '/content';
        $data->content_text = $data->content;
        if ($app) $data->content = $domain . '/topic/' . $id . '/content';

        $field              = 'id,cover,title,abstract,publish_time,read_count';
        $return['detail']   = $data;
        $return['comments'] = $this->comments($id);
        $return['splendid'] = $this->splendid($field, 5, $data->mhm_id, $id);

        if (request()->device_type == 'pc') {
            $top_category      = app(Category::class)->topCategoryByFull($data->fullcategorypath);
            $return['similar'] = $this->similar($id, $field, $top_category, 5, $data->mhm_id);
            // 上、下篇
            $return['prev_topic'] = $this->getPrev($data, 'id,title');
            $return['next_topic'] = $this->getNext($data, 'id,title');
        }
        return $return;
    }

    public function getPrev($data, $field = '*')
    {
        $empty = new ArrayObject();
        $prev  = $this
            ->field($field)
            ->where('update_time', '>', $data->update_time)
            ->where('mhm_id', '=', $data->mhm_id)
            ->order('update_time')
            ->findOrEmpty();
        return $prev->isEmpty() ? $empty : $prev;
    }

    public function getNext($data, $field = '*')
    {
        $empty = new ArrayObject();
        $next  = $this
            ->field($field)
            ->where('update_time', '<', $data->update_time)
            ->where('mhm_id', '=', $data->mhm_id)
            ->order('update_time', 'DESC')
            ->findOrEmpty();
        return $next->isEmpty() ? $empty : $next;
    }

    /** 添加阅读量 */
    public function addReadCount($id)
    {
        $data = $this->findOrEmpty($id);
        if (!$data->isEmpty()) {
            $data->read_count += 1;
            $data->save();
        }
    }

    /**
     * 资讯内容
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-19
     */
    public function content($id)
    {
        $info = $this->findOrEmpty($id);
        View::assign('title', $info->title);
        view::assign('content', $info->content);

        return View::fetch('content');
    }

    /**
     * @throws DbException
     */
    public function comments($topic_id)
    {
        $page = Paginator::getCurrentPage();
        $_mod = app(TopicComment::class)->with(['user.avatar_url'])->withCount(['reply', 'like', 'liked' => 'like'])->where('topic_id', $topic_id)->order('create_time', 'DESC');

        if ($page == 1) {
            $list = $_mod->paginate(static::getListRows());
            if (!$list->isEmpty()) {
                // 时间节点
                $time_node = $list->first()->create_time;
                cache('paginate_topic_' . request()->mid, $time_node);
            }
        } else {
            // 时间节点
            $time_node = cache('paginate_topic_' . request()->mid);
            // 数据
            if ($time_node) {
                $list = $_mod->where('create_time', '<=', $time_node)->paginate(static::getListRows());
            } else {
                $list = $_mod->paginate(static::getListRows());
            }
        }

        return $list;
    }

    // 详情页推荐资讯
    public function splendid($field = '*', $limit = 5, $mhm_id = 0, $id = 0)
    {
        $map = [];
        $mhm_id && $map[] = ['mhm_id', '=', $mhm_id];
        $id && $map[] = ['id', '<>', $id];
        return $this->with(['cover_url'])->field($field)->where($map)->order('best_sort', 'ASC')->limit($limit)->select();
    }

    // 资讯首页热门资讯
    public function popular($field = '*', $limit = 5, $mhm_id = 0)
    {
        $map = [];
        $mhm_id && $map[] = ['mhm_id', '=', $mhm_id];
        return $this->with(['cover_url'])->field($field)->where($map)->order('read_count', 'DESC')->limit($limit)->select();
    }

    // 详情页相关资讯
    public function similar($id, $field = '*', $top_category, $limit = 5, $mhm_id = 0)
    {
        $map = [];
        foreach ($top_category as $category) {
            $map[] = [
                ['id', '<>', $id],
                ['mhm_id', '=', $mhm_id],
                ['category', 'LIKE', '%,' . $category . ',%'],
            ];
        }

        return $this->with(['cover_url'])->field($field)->whereOr($map)->order('best_sort', 'ASC')->limit($limit)->select();
        // ->buildSql();
    }

    /**
     * 添加评论
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-07-02
     */
    public function postComment($id, $content)
    {
        $this->findOrFail($id);
        // 内容过滤
        $content = app(Common::class)->filterSensitive($content, $id, 'topic_comment');
        $new     = app(TopicComment::class)::create([
            'topic_id' => $id,
            'user_id'  => request()->mid,
            'content'  => $content,
        ]);

        if ($new->isEmpty()) throw new LogicException('添加失败');

        return $new;
    }

    /**
     * delComment
     * Author: 亓官雨树 <lucky.max@foxmail.com>
     * Date: 23/09/25
     *
     * @param $id
     */
    public function delComment($id)
    {
        $comment = app(TopicComment::class)->findOrEmpty($id);
        if (!$comment->delete()) throw new LogicException('删除失败');
    }

    /** 评论点赞状态 */
    public function updateCommentLikeStatus($id, $status)
    {
        // 获取对象模型
        $data['topic_comment_id'] = $id;
        $data['like_user_id']     = request()->mid;

        $model = app(TCL::class);
        $like  = $model
            ->withTrashed()
            ->where('topic_comment_id', $id)
            ->where('like_user_id', request()->mid)
            ->findOrEmpty();

        return $this->updateStatus($model, $like, $status, $data);
    }

    // 评论回复点赞状态
    public function updateReplyLikeStatus($id, $status)
    {
        // 获取对象模型
        $data['topic_comment_reply_id'] = $id;
        $data['like_user_id']           = request()->mid;

        $model = app(TCRL::class);
        $like  = $model
            ->withTrashed()
            ->where('topic_comment_reply_id', $id)
            ->where('like_user_id', request()->mid)
            ->findOrEmpty();

        return $this->updateStatus($model, $like, $status, $data);
    }

    // 更新点赞状态
    public function updateStatus($model, $like, $status, $data)
    {
        if ($like->isEmpty()) {
            // 不存在数据且status为1，添加数据
            if ($status == 1) {
                $like = $model::create($data);

                if ($like->isEmpty()) {
                    throw new LogicException('点赞失败');
                }
            } else {
                throw new LogicException('暂未点赞');
            }
        } else {
            // 存在数据根据status修改数据
            if ($status == 1) {
                $like->restore();
                $like = $model->find($like->id);
            } else {
                $like->delete();
            }
        }

        return $like;
    }

    // 添加评论回复
    public function addCommentReply($id, $data)
    {
        // 验证数据
        $this->getValidate()->scene('addReply')->failException()->check($data);
        // 定义参数
        $mid                      = request()->mid;
        $reply_mod                = app(TCR::class);
        $data['user_id']          = $mid;
        $data['topic_comment_id'] = $id;
        // 内容过滤
        $data['content'] = app(Common::class)->filterSensitive($data['content'], $id, 'topic_comment_reply');

        // 不能回复自己
        if ($data['reply_user_id'] == $mid) {
            throw new LogicException('不能@自己回复');
        }

        // 添加回复
        $reply = $reply_mod::create($data);

        if ($reply->isEmpty()) {
            throw new LogicException('添加失败');

        }

        $reply       = $reply_mod->with([
            'reply_user',
            'user.avatar_url',
        ])->findOrEmpty($reply->id);
        $reply->like = 0;

        // 事务处理消息 - 资讯点评回复提醒
        $param['send_user_id'] = $mid;
        // 有@用户时：写入@用户ID；无@用户时：写入点评课程的用户ID
        $param['recive_user_id'] = $data['reply_user_id'] ?: (app(TopicComment::class)->where('id', $id)->value('user_id') ?: 0);
        $param['notify_data_id'] = $id;
        $param['content']        = $data['content'];

        Event::subscribe(TopicEvent::class);
        Event::trigger('TopicNotify', $param);

        return $reply;
    }

    // 获取点评的评论信息

    /**
     * @throws DbException
     */
    public function getCommentReply($comment_id): array
    {
        $comment = app(TopicComment::class)
            ->with(['user.avatar_url'])
            ->withCount(['reply', 'like', 'liked' => 'like'])
            ->findOrFail($comment_id);

        $return['comment']      = $comment;
        $return['commentReply'] = $comment->replyDetail()->paginate(static::getListRows());

        return $return;
    }

    // 机构主页推荐资讯
    public function getSchoolRecommendTopics($mhm_id, $limit = 4)
    {
        $field = 'id,cover,title,abstract,publish_time,read_count';
        return $this->where('mhm_id', $mhm_id)->with(['cover_url'])->field($field)->order('best_sort', 'ASC')->limit($limit)->select();
    }

    /**
     * delCommentReply
     * Author: 亓官雨树 <lucky.max@foxmail.com>
     * Date: 23/09/25
     *
     * @param $id
     */
    public function delCommentReply($id)
    {
        $data = app(TCR::class)->findOrEmpty($id);
        if (!$data->delete()) throw new LogicException('删除失败');
    }
}
